// 测试封装的锁

#include <iostream>
#include <vector>
#include <unistd.h>
#include "Mutex.hpp"

/////////// 用自己封装的锁 !!!!
using namespace MutexModel;

int gticksts = 100; // 总票数
// // 申请锁
// Mutex mutex;

//************* 这个是普通写法 *************

// 这个是抢票 , 票数为 1000 , 多个线程来执行
// void *Tickets(void *args)
// {
//     std::string name = static_cast<const char *>(args);

//     // 申请锁
//     Mutex mutex;
//     while (1)
//     {

//         // 这里是临界区的开始
//         mutex.Lock(); // 加锁
//         if (gticksts > 0)
//         {
//             usleep(1000); // 1000 ms
//             std::cout << name << " sells ticket : " << gticksts << std::endl;
//             gticksts--;
//             mutex.Unlock();
//         } // 到这里临界区的结束 ..
//         else
//         {
//             mutex.Unlock();
//             break;
//         }
//     }

//     return nullptr;
// }

//************* 这个是普通写法 *************

//---------------------------------------------------------

//***************** RAII 写法更简洁 *****************

Mutex mutex; // 举个例子 , 演示 RAII 风格

void *Tickets(void *args)
{
    std::string name = static_cast<const char *>(args);

    while (1)
    {
        // 定义一个 LockGuard 对象 , 自动帮我们完成加锁和解锁
        LockGuard lockguard(mutex);
        {
            // 这里是临界区的开始
            if (gticksts > 0)
            {
                usleep(1000); // 1000 ms
                std::cout << name << " sells ticket : " << gticksts << std::endl;
                gticksts--;
            } // 到这里临界区的结束 ..
            else
            {
                // 这里需要解锁 !
                break;
            }
        } // 用括号括起来表示这个是临界区 , 对该区域进行保护 !!
    }

    return nullptr;
}

//***************** RAII 写法更简洁 *****************

int main()
{
    std::vector<pthread_t> threads;

    // 创建5个线程
    for (int i = 1; i <= 5; ++i)
    {
        pthread_t tid;
        char *name = new char[64]; // 开辟一个空间
        snprintf(name, 64, "thread-%d", i);
        int n = pthread_create(&tid, nullptr, Tickets, name);
        if (n == 0)
        {
            std::cout << "Create " << name << " Success ! " << std::endl;
            threads.emplace_back(tid);
        }
    }

    // 等待 5 个线程
    for (auto &tid : threads)
    {
        int n = pthread_join(tid, nullptr);
        if (n == 0)
        {
            std::cout << " Join Success ! " << std::endl;
        }
    }

    return 0;
}